package top.ruanlitao.shortlink.project.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.ruanlitao.shortlink.project.common.constant.RedisKeyConstant;
import top.ruanlitao.shortlink.project.common.convention.exception.ClientException;
import top.ruanlitao.shortlink.project.common.convention.exception.ServiceException;
import top.ruanlitao.shortlink.project.dao.entity.ShortLinkDO;
import top.ruanlitao.shortlink.project.dao.entity.ShortLinkGotoDO;
import top.ruanlitao.shortlink.project.dao.mapper.ShortLinkGotoMapper;
import top.ruanlitao.shortlink.project.dao.mapper.ShortLinkMapper;
import top.ruanlitao.shortlink.project.dto.req.RecycleBinRecoverReqDTO;
import top.ruanlitao.shortlink.project.dto.req.RecycleBinRemoveReqDTO;
import top.ruanlitao.shortlink.project.dto.req.RecycleBinSaveReqDTO;
import top.ruanlitao.shortlink.project.dto.req.ShortLinkRecycleBinPageReqDTO;
import top.ruanlitao.shortlink.project.dto.resp.ShortLinkPageRespDTO;
import top.ruanlitao.shortlink.project.service.RecycleBinService;

import java.util.Collections;

/**
 * 回收站接口实现层
 */
@Service
@RequiredArgsConstructor
public class RecycleBinServiceImpl extends ServiceImpl<ShortLinkMapper, ShortLinkDO> implements RecycleBinService {

    private final StringRedisTemplate stringRedisTemplate;
    private final ShortLinkGotoMapper shortLinkGotoMapper;

    @Override
    public void saveRecycleBin(RecycleBinSaveReqDTO requestParam) {
        LambdaUpdateWrapper<ShortLinkDO> updateWrapper = Wrappers.lambdaUpdate(ShortLinkDO.class)
                .eq(ShortLinkDO::getGid, requestParam.getGid())
                .eq(ShortLinkDO::getFullShortUrl, requestParam.getFullShortUrl())
                .eq(ShortLinkDO::getEnableStatus, 0);
        ShortLinkDO shortLinkDO = ShortLinkDO.builder()
                .enableStatus(1)
                .build();
        // 更新短链接的 enableStatus 为 1，表示不可用了
        int update = baseMapper.update(shortLinkDO, updateWrapper);
        if (update < 1) {
            throw new ClientException("短链接加入回收站失败");
        }
        // 因为将短链接加入回收站后短链接应该暂时是不能使用了的，所以需要将这条短链接的缓存删除
        stringRedisTemplate.delete(String.format(RedisKeyConstant.GOTO_SHORT_LINK_KEY, requestParam.getFullShortUrl()));
    }

    @Override
    public IPage<ShortLinkPageRespDTO> pageRecycleBinShortLink(ShortLinkRecycleBinPageReqDTO requestParam) {
        // 当有分组记录，就去查
        if (CollUtil.isNotEmpty(requestParam.getGidList())) {
            IPage<ShortLinkDO> resultPage = baseMapper.recycleBinPageLink(requestParam);
            return resultPage.convert(each -> BeanUtil.toBean(each, ShortLinkPageRespDTO.class));
        }
        // 没有分组记录，直接返回空
        Page<ShortLinkPageRespDTO> emptyPage = new Page<>(requestParam.getCurrent(), requestParam.getSize());
        emptyPage.setRecords(Collections.emptyList());
        emptyPage.setTotal(0);
        return emptyPage;
    }

    @Override
    public void recoverRecycleBin(RecycleBinRecoverReqDTO requestParam) {
        // 修改数据库中数据
        LambdaUpdateWrapper<ShortLinkDO> updateWrapper = Wrappers.lambdaUpdate(ShortLinkDO.class)
                .eq(ShortLinkDO::getGid, requestParam.getGid())
                .eq(ShortLinkDO::getFullShortUrl, requestParam.getFullShortUrl())
                .eq(ShortLinkDO::getEnableStatus, 1);
        ShortLinkDO shortLinkDO = ShortLinkDO.builder()
                .enableStatus(0)
                .build();
        int update = baseMapper.update(shortLinkDO, updateWrapper);
        if (update < 1) {
            throw new ServiceException("恢复短链接失败");
        }

        // 将缓存中的空数据删除掉
        stringRedisTemplate.delete(String.format(RedisKeyConstant.GOTO_NULL_VALUE_SHORT_LINK_KEY, requestParam.getFullShortUrl()));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void removeRecycleBin(RecycleBinRemoveReqDTO requestParam) {
        // 删除数据
        LambdaUpdateWrapper<ShortLinkDO> updateWrapper = Wrappers.lambdaUpdate(ShortLinkDO.class)
                .eq(ShortLinkDO::getFullShortUrl, requestParam.getFullShortUrl())
                .eq(ShortLinkDO::getGid, requestParam.getGid())
                .eq(ShortLinkDO::getEnableStatus, 1)
                .set(ShortLinkDO::getDelFlag, 1);
        ShortLinkDO updateShortLinkDO = ShortLinkDO.builder()
                .delTime(System.currentTimeMillis())
                .build();
        int update = baseMapper.update(updateShortLinkDO, updateWrapper);
        if (update < 1) {
            throw new ServiceException("短链接删除失败");
        }
        // 将 goto 表中的对应记录删除掉
        int delete = shortLinkGotoMapper.delete(
                Wrappers.lambdaQuery(ShortLinkGotoDO.class)
                        .eq(ShortLinkGotoDO::getFullShortUrl, requestParam.getFullShortUrl())
                        .eq(ShortLinkGotoDO::getGid, requestParam.getGid())
        );
        if (delete < 1) {
            throw new ServiceException("短链接删除失败");
        }
        // 将缓存中的空数据删除掉
        stringRedisTemplate.delete(String.format(RedisKeyConstant.GOTO_NULL_VALUE_SHORT_LINK_KEY, requestParam.getFullShortUrl()));
    }
}
